#pragma once
#ifndef _IRenderer_header_included_
#define _IRenderer_header_included_
#pragma warning( disable : 4275 ) // Because ReferenceCounter is not exported class.

#include <Engine/IIndexBuffer.h>
#include <Engine/Renderer/RendererStructs.h>

namespace fastbird
{
	class IVertexBuffer;
	class IShader;
	class ITexture;
	class ICamera;
	class Vec2I;
	class Vec3;
	class IObject;
	class IInputLayout;
	class IRasterizerState;
	class IBlendState;
	class IRenderer : public ReferenceCounter
	{
	public:
		static IRenderer* CreateD3D9Instance();
		static IRenderer* CreateD3D11Instance();
		static IRenderer* CreateOpenGLInstance();

		virtual ~IRenderer() {}
		virtual bool Init() = 0;
		virtual void Deinit() = 0;
		virtual void Clear(float r, float g, float b, float z) = 0;
		virtual void SetCamera(ICamera* pCamera) = 0;
		virtual ICamera* GetCamera() const = 0;
		virtual void UpdateFrameConstantsBuffer() = 0;
		virtual void UpdateObjectConstantsBuffer(void* pData) = 0;
		virtual void UpdateMaterialConstantsBuffer(void* pData) = 0;
		virtual void* MapMaterialParameterBuffer() = 0;
		virtual void UnmapMaterialParameterBuffer() = 0;
		virtual void Present() = 0;
		virtual void SetVertexBuffer(unsigned int startSlot, unsigned int numBuffers,
			IVertexBuffer* pVertexBuffers[], unsigned int strides[], unsigned int offsets[]) = 0;
		virtual void SetIndexBuffer(IIndexBuffer* pIndexBuffer) = 0;
		virtual void SetShader(IShader* pShader) = 0;
		virtual void SetInputLayout(IInputLayout* pInputLayout) = 0;
		virtual void SetTexture(ITexture* pTexture, BINDING_SHADER shaderType, unsigned int slot) = 0;
		virtual void SetPrimitiveTopology(PRIMITIVE_TOPOLOGY pt) = 0;
		virtual void DrawIndexed(unsigned indexCount, unsigned startIndexLocation, unsigned startVertexLocation) = 0;
		virtual void Draw(unsigned int vertexCount, unsigned int startVertexLocation) = 0;
		virtual unsigned GetWidth() const = 0;
		virtual unsigned GetHeight() const=0;
		virtual void SetWireframe(bool enable) = 0;
		virtual bool GetWireframe() const = 0;
		virtual MapData MapVertexBuffer(IVertexBuffer* pBuffer, UINT subResource, MAP_TYPE type, MAP_FLAG flag) = 0;
		virtual void UnmapVertexBuffer(IVertexBuffer* pBuffer, unsigned int subResource) = 0;
		
		virtual IVertexBuffer* CreateVertexBuffer(void* data, unsigned stride, unsigned numVertices, BUFFER_USAGE usage, BUFFER_CPU_ACCESS_FLAG accessFlag) = 0;
		virtual IIndexBuffer* CreateIndexBuffer(void* data, unsigned int numIndices, INDEXBUFFER_FORMAT format) = 0;
		virtual IShader* CreateShader(const char* filepath, IShader* pReloadingShader=0) = 0;
		virtual ITexture* CreateTexture(const Vec2I& size, int mipLevels, int arraySize) = 0;
		virtual ITexture* CreateTexture(const char* file, ITexture* pReloadingTexture=0) = 0;
		virtual ITexture* CreateTexture(void* data, int bpp, int width, int height) = 0;
		virtual IInputLayout* CreateInputLayout(INPUT_ELEMENT_DESC pDescs[], unsigned count, 
			const void* pShaderBytecodeWithInputSignature, unsigned byteLength) = 0;

		virtual void FindOrCreateSamplerState(ITexture* pTexture, const SAMPLER_DESC& desc) = 0;
		virtual void FindOrCreateRasterizerState(IObject* pObject, const RASTERIZER_DESC& desc) =0;
		virtual void FindOrCreateBlendState(IObject* pObject, const BLEND_DESC& desc) = 0;
		virtual void SetRasterizerState(IRasterizerState* pRasterizerState) = 0;
		virtual void SetBlendState(IBlendState* pBlendState) = 0;

		virtual void InitFrameProfiler(float dt) = 0;
		virtual const RENDERER_FRAME_PROFILER& GetFrameProfiler() const = 0;
	};
}

#endif //_IRenderer_header_included_